/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "i2c.h"
#include "tim.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include "generator.h"
#include "measurement.h"
#include "syndet.h"
#include "ssd1306.h"
#include "utility.h"
#include "display.h"
#include "stm32f0xx_it.h"
#include "bbb.h"
#include "sin128.h"
#include "usart.h"


/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
	
#define BEEPDUR	50

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
sd_Results* Res;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */


const uint16_t FreqList[] = 	{1000 ,	100,	10,	1};
const uint16_t CyclesList[] =	{400,	100,	10,	4};
const uint16_t DropList[] =		{200,	50,		3,	1};
static int8_t ActiveIndex = 0;

//Default parameters
uint8_t IsMeasRequested = 0;			//Flag to start the measurement
int8_t FreqOrder = +1;					//Normally highest frequency goes first (+1), if (-1) measurement starts with lowest frequency
uint8_t IsSlowMode = 0;					//4x more measurement cycles if set
uint8_t IsAutoRange = 0;
uint8_t IsStdevRequested = 0;

static void RunSingleMeasurement(void){
	  for(uint8_t i=ActiveIndex; i<UT_SIZEOFARRAY(FreqList); i++){
		  bbb_Beep(bbb_ToneTd_Med, BEEPDUR);
		  bbb_Beep(bbb_ToneTd_None, BEEPDUR);
	  }

	  bbb_UpdateBtns();
	  disp_DrawProggressScreen(bbb_GetTemp(), bbb_GetVbat());	//Draw loading screen and start the initial test
	  sd_HandleMeasurementSync(FreqList[ActiveIndex], (IsSlowMode) ? (4*CyclesList[ActiveIndex]) : (CyclesList[ActiveIndex]), DropList[ActiveIndex]);
	  Res = sd_GetMeasurementResults();
	  disp_DrawResultsScreen(Res, 0);	//Display the results, display size 128 x 32 px, font 7 x 10 px, 18 chars x 3 rows

	  uint8_t ToneSel = bbb_ToneTd_High;
	  if(Res&&Res->FMI) ToneSel = bbb_ToneTd_Low;
	  bbb_Melody2(bbb_ToneTd_Med, ToneSel, BEEPDUR);
}


/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

	for(volatile uint32_t i=0; i<100000; i++);

  /* USER CODE END 1 */
  

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  

  LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SYSCFG);
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);

  /* System interrupt init*/

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC_Init();
  MX_I2C1_Init();
  MX_TIM16_Init();
  MX_TIM1_Init();
  MX_TIM17_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */

  //MX_USART1_UART_Init();

  LL_DBGMCU_APB1_GRP2_FreezePeriph(LL_DBGMCU_APB1_GRP2_TIM1_STOP);
  LL_DBGMCU_APB1_GRP1_FreezePeriph(LL_DBGMCU_APB1_GRP2_TIM16_STOP|LL_DBGMCU_APB1_GRP2_TIM17_STOP);//__HAL_DBGMCU_FREEZE_TIM1();
  LL_SYSTICK_EnableIT();
  gen_Init();												//Initialize signal generator output as soon as posible

  sin128_Init();											//Prepare sin lookup table
  bbb_Init();												//Initialize battery, button, buzzer module
  meas_Init();												//Initialize measurement module
  sd_init();												//Initialize synchronous detection (using generator and measurement modules)
  ssd1306_Init();											//Initialize the screen


  bbb_UpdateBtns();
  disp_DrawInitScreen(bbb_GetTemp(), bbb_GetVbat());
  bbb_Melody3(bbb_ToneTd_Low, bbb_ToneTd_Med, bbb_ToneTd_High, 2*BEEPDUR);


  //DURING BOOT
  	  //No button pressed - no measurement after startup
  	  //Up btn pressed - autorange measurement starting with lowest frequency ang increasing
  	  //Dn btn pressed - autorange measurement starting with highest frequency and decreasing
  	  //Both btns pressed (maybe short finder)
  //WHEN NO MEASUREMENT IS ACTIVE
  	  //UP BTN
  	  	  //Single release - decrease measurement frequency
  	  	  //Double release - increase measurement frequency
  	  	  //Long release - display secondary screen with stdevs
  	  //DN BTN
  	  	  //Single release - start measurement
  	  	  //Double release - long duration measurement
  	  	  //If button is pressed when measurement finishes it is automatically repeated




  if(BtnUp.PrevBtnState == 1){
	  ActiveIndex = UT_SIZEOFARRAY(FreqList)-1;
	  FreqOrder = -1;
	  IsAutoRange = 1;
	  //IsMeasRequested = 1;
  }

  if(BtnDn.PrevBtnState == 1){
	  ActiveIndex = 0;
	  FreqOrder = +1;
	  IsAutoRange = 1;
	  //IsMeasRequested = 1;
  }


  //Initial possible autorange sweep (btn up or dn during the boot)
  for(;;){													//After startup measurement with automatic range check is performed

	  if(!IsAutoRange) break;

	  bbb_Beep(bbb_ToneTd_None, 500);
	  RunSingleMeasurement();
	  if(Res->FMI){											//If FMI is set we should just change frequency and repeat the measurement unless limit frequency already reached
		  if( ( FreqOrder >= 0 ) && ( ActiveIndex < (UT_SIZEOFARRAY(FreqList) - 1) ) ){
			  ActiveIndex += FreqOrder;
			  continue;
		  }
		  else if( ( FreqOrder < 0 ) && ( ActiveIndex > 0 ) ){
			  ActiveIndex += FreqOrder;
			  continue;
		  }
		  else{
			  break; 										//All frequencies tried but still FMI, fw might continue to secondary phase
		  }
	  }
	  else{
		  break;											//If measurement finished without errors cycle may end and fw might continue to secondary phase
	  }
  }


  //Manual control after optional initial autorange measurement
  bbb_UpdateBtns();
  for(;;){
	  bbb_UpdateBtns();

	  if(BtnUp.PrevBtnEvt == bbb_EvtTd_SingleReleased){
		  if(ActiveIndex<UT_SIZEOFARRAY(FreqList)-1) ActiveIndex++;		//lower frequency

		  disp_DrawFrequencyPopup(FreqList[ActiveIndex]);
		  bbb_Beep(0, 500);
		  disp_DrawResultsScreen(Res, IsStdevRequested);
	  }
	  else if(BtnUp.PrevBtnEvt == bbb_EvtTd_DoubleReleased){			//higher frequency
		  if(ActiveIndex>0) ActiveIndex--;

		  disp_DrawFrequencyPopup(FreqList[ActiveIndex]);
		  bbb_Beep(0, 500);
		  disp_DrawResultsScreen(Res, IsStdevRequested);
	  }
	  else if(BtnUp.PrevBtnEvt == bbb_EvtTd_LongReleased){
		  //Switch screen - means/stdevs
		  IsStdevRequested ^= 0x1;
		  disp_DrawResultsScreen(Res, IsStdevRequested);
	  }


	  if(BtnDn.PrevBtnEvt == bbb_EvtTd_SingleReleased){
		  IsSlowMode = 0;
		  IsMeasRequested = 1;
	  }
	  else if(BtnDn.PrevBtnEvt == bbb_EvtTd_LongReleased){
		  IsSlowMode = 1;
		  IsMeasRequested = 1;
	  }


	  if(IsMeasRequested){
		  IsMeasRequested = 0;

		  RunSingleMeasurement();
		  bbb_UpdateBtns();

		  if(BtnDn.PrevBtnState == 1){
			  IsMeasRequested = 1;
		  }
	  }
  }


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  LL_FLASH_SetLatency(LL_FLASH_LATENCY_1);

  if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_1)
  {
  Error_Handler();  
  }
  LL_RCC_HSE_Enable();

   /* Wait till HSE is ready */
  while(LL_RCC_HSE_IsReady() != 1)
  {
    
  }
  LL_RCC_HSI14_Enable();

   /* Wait till HSI14 is ready */
  while(LL_RCC_HSI14_IsReady() != 1)
  {
    
  }
  LL_RCC_HSI14_SetCalibTrimming(16);
  LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE_DIV_1, LL_RCC_PLL_MUL_6);
  LL_RCC_PLL_Enable();

   /* Wait till PLL is ready */
  while(LL_RCC_PLL_IsReady() != 1)
  {
    
  }
  LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);

   /* Wait till System clock is ready */
  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
  {
  
  }
  LL_Init1msTick(48000000);
  LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK);
  LL_SetSystemCoreClock(48000000);
  LL_RCC_HSI14_EnableADCControl();
  LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_SYSCLK);
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(char *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
